home *** CD-ROM | disk | FTP | other *** search
- /* Convert relative to absolute pathnames
- * Copyright 1991 Phil Karn, KA9Q
- */
- #include "global.h"
- #include "commands.h"
- #include "dirutil.h"
- #ifdef CALLSERVER
- extern char *CDROM; /* buckbook.c: defines CDROM drive letter e.g. "s:" */
- #endif
-
- #if !defined(_lint)
- static char rcsid[] OPTIONAL = "$Id: pathname.c,v 1.12 1996/09/04 01:34:13 root Exp root $";
- #endif
-
- void crunch (char *buf,const char *path);
-
- /* Given a working directory and an arbitrary pathname, resolve them into
- * an absolute pathname. Memory is allocated for the result, which
- * the caller must free
- */
- char *
- pathname (cd, path)
- const char *cd; /* Current working directory */
- const char *path; /* Pathname argument */
- {
- register char *buf;
- #ifdef MSDOS
- char *cp,c;
- char *tbuf = NULLCHAR;
- int tflag = 0;
- #endif
- #ifdef CALLSERVER
- int drive = 0; /* is there a drive spec to preserve? */
- #endif
-
- if(cd == NULLCHAR || path == NULLCHAR)
- return NULLCHAR;
-
- #ifdef MSDOS
- /* If path has any backslashes, make a local copy with them
- * translated into forward slashes
- */
- if (strchr (path, '\\') != NULLCHAR){
- tflag = 1;
- cp = tbuf = strdup (path);
- while ((c = *path++) != '\0'){
- if(c == '\\')
- *cp++ = '/';
- else
- *cp++ = c;
- }
- *cp = '\0';
- path = tbuf;
- }
- #endif
-
- /* Strip any leading white space on args */
- cd = skipwhite (cd);
- path = skipwhite (path);
-
- #ifdef CALLSERVER
- if (CDROM != NULLCHAR && strncmp (path, CDROM, 2) == 0) {
- buf = strdup (path);
- return buf;
- }
- if (CDROM != NULLCHAR && strncmp(cd, CDROM, 2) == 0)
- drive = 1;
- /* make a note */
- #endif
- /* Allocate and initialize output buffer; user must free */
- buf = mallocw ((unsigned)strlen (cd) + strlen (path) + 10); /* fudge factor */
- buf[0] = '\0';
-
- /* Interpret path relative to cd only if it doesn't begin with "/" */
- if (path[0] != '/') {
- if (cd[0] != '/' && cd[0] != '.')
- strcpy (buf, ".");
- crunch (buf, cd);
- }
-
- #ifdef CALLSERVER
- else
- drive = 0;
- #endif
- crunch (buf, path);
-
- /* Special case: null final path means the root directory */
- if (buf[0] == '\0'){
- buf[0] = '/';
- buf[1] = '\0';
- }
- #ifdef MSDOS
- if (tflag && tbuf)
- free (tbuf);
- #endif
- #ifdef CALLSERVER
- if (drive) {
- cp = buf;
- while (*cp != '\0')
- *cp = *(cp++ + 1);
- }
- #endif
- return buf;
- }
-
-
- /* Process a path name string, starting with and adding to
- * the existing buffer
- */
- void
- crunch (buf, path)
- char *buf;
- register const char *path;
- {
- register char *cp;
-
-
- if (!strncmp ("./", path, 2) || !strncmp ("../", path, 3)) {
- strcpy (buf, path);
- return;
- }
- cp = buf + strlen (buf); /* Start write at end of current buffer */
-
- /* Now start crunching the pathname argument */
- for ( ; ; ) {
- /* Strip leading /'s; one will be written later */
- while (*path == '/')
- path++;
- if (*path == '\0')
- break; /* no more, all done */
- /* Look for parent directory references, either at the end
- * of the path or imbedded in it
- */
- if (strcmp (path, "..") == 0 || strncmp (path, "../", 3) == 0){
- /* Hop up a level */
- if ((cp = strrchr (buf, '/')) == NULLCHAR)
- cp = buf; /* Don't back up beyond root */
- *cp = '\0'; /* In case there's another .. */
- path += 2; /* Skip ".." */
- while (*path == '/') /* Skip one or more slashes */
- path++;
- /* Look for current directory references, either at the end
- * of the path or imbedded in it
- */
- } else if (strcmp (path, ".") == 0 || strncmp (path, "./", 2) == 0){
- /* "no op" */
- path++; /* Skip "." */
- while (*path == '/') /* Skip one or more slashes */
- path++;
- } else {
- /* Ordinary name, copy up to next '/' or end of path */
- *cp++ = '/';
- while (*path != '/' && *path != '\0')
- *cp++ = *path++;
- }
- }
- *cp++ = '\0';
- }
-